PartialEq trait
GPT-4.icon
PartialEqトレイトは、Rustで型同士を比較するための標準的なトレイトです。
このトレイトを実装することで、その型のインスタンスを比較できるようになります。PartialEqを実装している型は==や!=といった比較演算子を使えるようになります。
以下に詳細を解説します。
---
PartialEq トレイトの概要
PartialEq トレイトは次のように定義されています。
code:rust
pub trait PartialEq<Rhs = Self> {
fn eq(&self, other: &Rhs) -> bool;
fn ne(&self, other: &Rhs) -> bool { !self.eq(other) }
}
関連型 Rhs
Rhsは比較する相手の型を表します。デフォルトではSelf(つまり同じ型同士の比較)になっています。
eq メソッド
2つの値が等しいかどうかを判断します。==演算子はこのメソッドを使用しています。
ne メソッド
2つの値が等しくないかどうかを判断します。!=演算子はこのメソッドを使用します。デフォルトの実装では!eqを呼び出しています。
---
デリファルト実装
PartialEqはRustの多くの標準型でデリファルト実装されています。たとえば次のような型では自動的に利用可能です。
プリミティブ型(i32, f64, char, など)
標準ライブラリの型(String, Vec<T>, など)
配列とスライス([T; N], [T])
デリファルトってなんやねんmrsekut.icon
カスタム型への実装
カスタム型にPartialEqを実装することで、その型のインスタンス同士を比較できるようになります。例を見てみましょう。
手動で実装する例
code:rust
struct Point {
x: i32,
y: i32,
}
impl PartialEq for Point {
fn eq(&self, other: &Self) -> bool {
self.x == other.x && self.y == other.y
}
}
fn main() {
let p1 = Point { x: 1, y: 2 };
let p2 = Point { x: 1, y: 2 };
let p3 = Point { x: 3, y: 4 };
println!("{}", p1 == p2); // true
println!("{}", p1 == p3); // false
}
#[derive(PartialEq)] を使う
手動で実装する代わりに、ほとんどの場合は#[derive(PartialEq)]を使うことで自動的に実装できます。
code:rust
struct Point {
x: i32,
y: i32,
}
fn main() {
let p1 = Point { x: 1, y: 2 };
let p2 = Point { x: 1, y: 2 };
let p3 = Point { x: 3, y: 4 };
println!("{}", p1 == p2); // true
println!("{}", p1 == p3); // false
}
この方法では、型のすべてのフィールドがPartialEqを実装している必要があります。
---
部分順序関係での注意
PartialEqという名前の通り、このトレイトは「部分的な等価性(partial equality)」を表します。そのため、次の特徴があります:
1. 対称性(Symmetry)
a == bであれば、b == aも成立します。
2. 推移性(Transitivity)
a == bかつb == cなら、a == cも成立します。
3. 反射性(Reflexivity)
a == aは常に成立します。
ただし、浮動小数点型(f32, f64)ではNaNという特例があるため、反射性が破れます。たとえば、NaN != NaNはtrueになります。
---
EqトレイトはPartialEqの拡張で、すべての値が完全な順序関係を持つ場合に使用されます。Eqを実装するにはPartialEqを先に実装する必要があります。
code:rust
pub trait Eq: PartialEq<Self> {}
多くの型では#[derive(Eq)]で自動的に実装できます。
---
PartialEqの使い所
カスタム型のインスタンス同士を比較する必要がある場合。
標準型ではデフォルトの比較ロジックを変更したい場合(たとえばフィールドの一部だけを比較対象にするなど)。
PartialEqはRustの比較演算の基本を支える重要なトレイトであり、特にジェネリックプログラミングで頻繁に使われます。